package com.ncr.teradata.bireport;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.LinkedHashSet;

/**
 * ReportData.java
 * 报表数据类（即数据立方体DataCube），每一个ReportData对象里封装了一个报表所需要的数据
 *
 * @author ylpeng
 * @date Mar 12, 2007
 */
public class ReportData implements java.io.Serializable{
	//报表中的数据集合
	private List data = new ArrayList();
	
	//数据集中列的数量
	private int columnCount = 0;
	
	//数据集中各列的名称
	private String[] columnName = null;
	
	//数据集中各列的数据类型
	private String[] columnType = null;
	
	//数据集中各列的标签
	private String[] columnLabel = null;
	
	//数据集中各列数据类型对应的JAVA类名称
	//private String[] columnClassName = null;
	
	//数据集中列对应的下标位置
	private Map columnIndex = new HashMap();
	
	//数据集中每一列排重复后的所有取值
	private Object[] columnValues = null;
	
	/**
	 * 构造函数
	 */
	public ReportData(){}
	
	/**
	 * 构造函数，用ResultSet来填充自身
	 *
	 *@param rs ResultSet 数据库结果集
	 */
	public ReportData(ResultSet rs){
		populate(rs);
	}
	
	/**
	 * 使用给定ResultSet对象中的数据来填充自身
	 *
	 *@param rs ResultSet 数据库结果集
	 */
	public void populate(ResultSet rs){
		data.clear();
		try{
			ResultSetMetaData md = rs.getMetaData();
			populateMetadata(md);
			while(rs.next()){
				Object[] row = new Object[columnCount];
				for(int i = 0; i < row.length; i++){
					if(columnType[i].indexOf("CHAR") != -1){
						//row[i] = rs.getObject(i + 1);
						row[i] = rs.getString(i + 1).trim();
						((TreeSet)columnValues[i]).add(row[i]);
					}
					else
						row[i] = rs.getBigDecimal(i + 1);
				}
				data.add(row);
			}
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}
	
	/**
	 * 用给定的ResultSetMetaData对象中的数据来填充自身的元数据信息
	 *
	 *@param rsmd ResultSetMetaData 数据库结果集元数据
	 */
	public void populateMetadata(ResultSetMetaData rsmd){
		try{
			columnCount = rsmd.getColumnCount();
			columnName = new String[columnCount];
			columnType = new String[columnCount];
			columnLabel = new String[columnCount];
			//columnClassName = new String[columnCount];
			columnValues = new Object[columnCount];
			for(int i = 1; i <= columnCount; i++){
				columnName[i - 1] = rsmd.getColumnName(i);
				columnType[i - 1] = rsmd.getColumnTypeName(i).toUpperCase();
				columnLabel[i - 1] = rsmd.getColumnLabel(i);
				//columnClassName[i - 1] = rsmd.getColumnClassName(i);
				columnIndex.put(columnName[i - 1].toUpperCase(),new Integer(i-1));
				columnValues[i - 1] = new TreeSet();
			}
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}
	
	/**
	 * 得到报表中的数据集
	 *
	 *@return List 返回报表中的数据集
	 */
	public List getData(){
		return data;
	}
	
	/**
	 * 得到数据集列的数量
	 *
	 *@return int 返回数据集列的数量
	 */
	public int getColumnCount(){
		return columnCount;
	}
	
	/**
	 * 得到数据集中列的名称
	 *
	 *@param i int 第几列
	 *@return String 返回指定列的名称
	 */
	public String getColumnName(int i){
		return columnName[i - 1];
	}
	
	/**
	 * 得到数据集中列的数据类型
	 *
	 *@param i int 第几列
	 *@return String 返回指定列的数据类型
	 */
	public String getColumnType(int i){
		return columnType[i - 1];
	}
	
	/**
	 * 得到数据集中列的标签
	 *
	 *@param i int 第几列
	 *@return String 返回指定列的标签
	 */
	public String getColumnLabel(int i){
		return columnLabel[i - 1];
	}
	
	/**
	 * 得到数据集中列的数据类型对应的JAVA类名称
	 *
	 *@param i int 第几列
	 *@return String 返回指定列的JAVA类名称
	 */
	//public String getColumnClassName(int i){
	//	return columnClassName[i - 1];
	//}
	
	/**
	 * 得到数据集中列名对应的下标位置
	 *
	 *@param colNm String 列的名称
	 *@return int 返回列名对应的下标位置
	 */
	public int getColumnIndex(String colNm){
		if(columnIndex.containsKey(colNm.toUpperCase()))
			return ((Integer)columnIndex.get(colNm.toUpperCase())).intValue();
		else
			return -1;
	}
	
	/**
	 * 得到某一列的所有取值（排除重复值，各取值按升序排列）
	 *
	 *@param i int 第几列
	 *@return Object[] 返回指定列的取值集合
	 */
	public Object[] getColumnValues(int i){
		//return ((TreeSet)columnValues[i]).toArray();
		LinkedHashSet values = new LinkedHashSet();
		for (int j = 0; j < data.size(); j++){
			Object[] row = (Object[])data.get(j);
			values.add(row[i]);
		}
		return values.toArray();
	}
	
	/**
	 * 得到某一列的所有取值，带有限制条件（排除重复值，各取值按升序排列）
	 *
	 *@param colIdx int 第几列
	 *@param restrictColIdx 要添加限制条件的列的下标位置
	 *@param restrictValue  要添加的限制条件的值
	 *@return Object[] 返回指定列的取值集合
	 */
	public Object[] getColumnValues(int colIdx,int restrictColIdx,String restrictValue){
		LinkedHashSet values = new LinkedHashSet();
		for (int i = 0; i < data.size(); i++){
			Object[] row = (Object[])data.get(i);
			if (((String)row[restrictColIdx]).equals(restrictValue))
				values.add(row[colIdx]);
		}
		return values.toArray();
	}
	
	/**
	 * 得到某一列的最大值
	 *
	 *@param i int 第几列
	 *@return Object 返回指定列的最大值
	 */
	public Object getColumnMaxValue(int i){
		if (((TreeSet)columnValues[i]).size() > 0)
			return ((TreeSet)columnValues[i]).last();
		else
			return "";
	}
	
	/**
	 * 得到某一列的最大值（带有条件限制）
	 *
	 *@param colIdx int 第几列
	 *@param restrictColIdx 要添加限制条件的列的下标位置
	 *@param restrictValue  要添加的限制条件的值
	 *@return Object 返回指定列的最大值
	 */
	public Object getColumnMaxValue(int colIdx,int restrictColIdx,String restrictValue){
		TreeSet values = new TreeSet();
		for (int i = 0; i < data.size(); i++){
			Object[] row = (Object[])data.get(i);
			if (((String)row[restrictColIdx]).equals(restrictValue))
				values.add(row[colIdx]);
		}
		if (values.size() > 0)
			return values.last();
		else
			return "";
	}
	
	/**
	 * 得到某一列的最小值
	 *
	 *@param i int 第几列
	 *@return Object 返回指定列的最小值
	 */
	public Object getColumnMinValue(int i){
		if (((TreeSet)columnValues[i]).size() > 0)
			return ((TreeSet)columnValues[i]).first();
		else
			return "";
	}
	
	/**
	 * 得到某一列的最小值（带有条件限制）
	 *
	 *@param colIdx int 第几列
	 *@param restrictColIdx 要添加限制条件的列的下标位置
	 *@param restrictValue  要添加的限制条件的值
	 *@return Object 返回指定列的最小值
	 */
	public Object getColumnMinValue(int colIdx,int restrictColIdx,String restrictValue){
		TreeSet values = new TreeSet();
		for (int i = 0; i < data.size(); i++){
			Object[] row = (Object[])data.get(i);
			if (((String)row[restrictColIdx]).equals(restrictValue))
				values.add(row[colIdx]);
		}
		if (values.size() > 0)
			return values.first();
		else
			return "";
	}
	
	/**
	 * 根据数据的ID值找到对应的Name值
	 * （这种方法在客户端频繁调用时性能可能会存在问题，有待想办法用别的方法来实现这个功能）
	 *
	 *@param idColIdx int ID列的下标位置
	 *@param nameColIdx int Name列的下标位置
	 *@param idValue String ID值
	 *@return Object 返回ID对应的Name值
	 */
	public Object getNameValueByID(int idColIdx,int nameColIdx,String idValue){
		Object nameValue = null;
		for (int i = 0; i < data.size(); i++){
			Object[] row = (Object[])data.get(i);
			if (((String)row[idColIdx]).equals(idValue)){
				nameValue = row[nameColIdx];
				break;
			}
		}
		return nameValue;
	}
}